package com.interpreter.part1;

import com.interpreter.common.CommonUtil;
import com.interpreter.common.Constant;
import com.interpreter.common.Token;

import java.math.BigDecimal;


public class Interpreter {

  public String text;
  public int pos;
  public Token currentToken;

  public Interpreter(String text) {
    this.text = text;
    this.pos = 0;
    this.currentToken = null;
  }

  public void error() {
    throw new RuntimeException("解析给定文本出现错误,请检查");
  }

  // 遍历字符数组, 然后对每个字符进行判断, 将其包装为 Token 之后进行返回
  public Token getNextToken() {
    if (this.pos > this.text.length() - 1) {
      return Token.EofToken();
    }
    char currentProcessChar = this.text.charAt(this.pos);
    // 如果 char 为数字, 则包装为 INTEGER token
    if (CommonUtil.isInteger(currentProcessChar)) {
      Token token = new Token(Constant.TOKEN_INTEGER, new BigDecimal(String.valueOf(currentProcessChar)));
      this.pos++;
      return token;
    }
    // 如果 char 为 + 符号, 则包装为 PLUS token
    if (currentProcessChar == '+') {
      Token token = new Token(Constant.TOKEN_PLUS, '+');
      this.pos++;
      return token;
    }
    // 以上两者都不是, 则证明给定的文本中包含了非法字符, 我们抛出错误, 拒绝执行
    this.error();
    return null;
  }

  // 检查当前 token 的类型是不是我们想要的, 如果是我们想要的, 则返回下一个 token
  // 如果不是我们预计的 token 类型, 则报错
  // 此处可以看做最简单的语法检查
  public void checkAndMoveToNext(String tokenType) {
    if (this.currentToken.tokenType.equals(tokenType)) {
      this.currentToken = this.getNextToken();
    } else {
      this.error();
    }
  }

  public Object expression() {
    this.currentToken = this.getNextToken();
    Token left = this.currentToken;
    this.checkAndMoveToNext(Constant.TOKEN_INTEGER);
    Token op = this.currentToken;
    this.checkAndMoveToNext(Constant.TOKEN_PLUS);
    Token right = this.currentToken;
    this.checkAndMoveToNext(Constant.TOKEN_INTEGER);
    return ((BigDecimal)left.value).add((BigDecimal)right.value);
  }

  public static void main(String[] args) {
    String text = "8+9";
    Interpreter interpreter = new Interpreter(text);
    Object result = interpreter.expression();
    System.out.println(result);
  }
}
